package wasnake.engine;
import java.awt.Color;
import java.awt.event.KeyEvent;

import java.util.ArrayList;
import wasnake.actors.Actor;
import wasnake.actors.Cell;
import wasnake.actors.Food;
import wasnake.actors.Moose;
import wasnake.actors.Snake;
import wasnake.grid.Direction;
import wasnake.grid.Grid;
import wasnake.grid.Location;
import wasnake.gui.GridPanel;

public class Engine implements Runnable{
	private ArrayList<Actor> listOfActors;
	private Thread thread;
	private Grid<Cell> grid;
	private GridPanel panel;
	private int difficulty;
	private Snake snake;
	private Moose moose;
	private int score;
	private boolean hasMoved;
	
	public Engine(int size, int difficulty, GridPanel panel){
		listOfActors = new ArrayList<Actor>();
		grid = new Board<Cell>(size, size);
		this.panel = panel;
		panel.setGrid(grid);
		this.difficulty = difficulty;
		snake = new Snake(Color.GREEN, Direction.NORTH);
		snake.putSelfInGrid(grid, new Location(49, 25));
		listOfActors.add(snake);
		createFood();
		createMoose();
		this.score = 0;
	}

	private Location createEmptyLocation(){
		Location loc;
		synchronized(grid) {
			do{
				int col = (int)(Math.random() * grid.getNumCols()),
				row = (int)(Math.random() * grid.getNumRows());
				loc = new Location(row, col);
			}while(grid.get(loc) != null);
		}
		return loc;
	}
	
	private void createMoose() {
		synchronized(grid) {
			Location mooseLoc = createEmptyLocation();
			Moose moose = new Moose(Color.BLACK, Direction.NORTH);
			moose.putSelfInGrid(grid, mooseLoc);
			listOfActors.add(moose);
		}
	}
	
	private void createFood() {
		synchronized(grid) {
			Location foodLoc = createEmptyLocation();
			Food newFood = new Food(Color.ORANGE);
			newFood.putSelfInGrid(grid, foodLoc);
			score();
		}
	}
	
	private void score() {
		if (difficulty == 1)
			score++;
		else if (difficulty == 2)
			score += 2;
		else
			score += 3;
	}

	public void keyPressed(KeyEvent evt)
    {	
		
	        switch(evt.getKeyCode())
	        {	
	        	//move the snake
	            case KeyEvent.VK_RIGHT :
	            	if(snake.getDirection() == Direction.WEST || !hasMoved) {
	            		System.out.println("Not a valid move");
	            	} else {
		            	snake.setDirection(Direction.EAST);
		            	System.out.println("right");
	            	}
	            	break;
	            case KeyEvent.VK_LEFT : 
	            	if(snake.getDirection() == Direction.EAST || !hasMoved) {
	            		System.out.println("Not a valid move");
	            	} else {
		            	snake.setDirection(Direction.WEST);
		            	System.out.println("left");
	            	}
	            	break;
	            case KeyEvent.VK_UP:
	            	if(snake.getDirection() == Direction.SOUTH || !hasMoved) {
	            		System.out.println("Not a valid move");
	            	} else {
		            	snake.setDirection(Direction.NORTH);
		            	System.out.println("up");
	            	}
	            	break;
	            case KeyEvent.VK_DOWN:
	            	if(snake.getDirection() == Direction.NORTH || !hasMoved) {
	            		System.out.println("Not a valid move");
	            	} else {
		            	snake.setDirection(Direction.SOUTH);
		            	System.out.println("down");
	            	}
	            	break;
	        }
	        hasMoved = false;
		
    }
	
	@Override
	public void run() {
		thread = new Thread () {
			public void run() {
				synchronized(grid) {
					while (true) {
						for(Actor actor: listOfActors){
							System.out.println("acting for the actor:");
							if(actor.getGrid() == null) {
								listOfActors.remove(actor);
								if(actor.getClass() == Moose.class)
									createMoose();
								if(actor.getClass() == Food.class)
									createFood();
							} else
								actor.act();
							hasMoved = true;
						}
						
						
						boolean isFood = false;
						for(Location loc: grid.getOccupiedLocations()) {
							if(grid.get(loc).getOwner().getClass() == Food.class) 
								isFood = true;
						}
						
						if(!isFood) {
							createFood();
							panel.setScore(score);
						}
						
						
						
						boolean isSnake = false;
						for(Location loc: grid.getOccupiedLocations()) {
							if(grid.get(loc).getOwner().getClass() == Snake.class)
								isSnake = true;
						}
						
						if(!isSnake)  {
							panel.gameover();
							thread.stop();
						}
						
						
						panel.repaint();
						panel.requestFocus();
						try {
							if(difficulty == 1)
								thread.sleep(250);
							else if(difficulty == 2)
								thread.sleep(100);
							else
								thread.sleep(50);
							
						} catch (InterruptedException e) {
							System.out.println("main thread was interrrupted");
						}
					}
				}
			}
		};
		thread.start();
	}
}
